package com.mengniu.common.social.mengniu98k;

import cn.hutool.core.codec.Base64;
import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.mengniu.commerce.common.core.constant.CacheConstants;
import com.mengniu.commerce.common.core.utils.JsonUtils;
import com.mengniu.commerce.common.redis.util.RedisUtils;
import com.mengniu.common.social.config.utils.AuthRedisStateCache;
import com.mengniu.common.social.mengniu98k.body.TokenRequestBody;
import com.mengniu.common.social.mengniu98k.source.AuthMengniuSource;
import com.xkcoding.http.support.HttpHeader;
import me.zhyd.oauth.config.AuthConfig;
import me.zhyd.oauth.exception.AuthException;
import me.zhyd.oauth.model.AuthCallback;
import me.zhyd.oauth.model.AuthToken;
import me.zhyd.oauth.request.AuthDefaultRequest;
import me.zhyd.oauth.utils.HttpUtils;
import me.zhyd.oauth.utils.UrlBuilder;

import java.time.Duration;

/**
 * @author: dgyu-398305246@qq.com
 * @createTime: 2023年12月04 11:27:36
 * @description:
 */
public class AuthMengniu98kRequest extends AuthDefaultRequest {

    public static final String SERVER_URL = SpringUtil.getProperty("justauth.type.mengniu98k.server-url");

    protected AuthMengniuSource authMengniuSource;

    /**
     * 构造方法
     *
     * @param config
     * @param stateCache
     */
    public AuthMengniu98kRequest(AuthConfig config, AuthRedisStateCache stateCache) {
        super(config, AuthMengniu98kSource.MENGNIU98K, stateCache);
        this.authMengniuSource = AuthMengniu98kSource.MENGNIU98K;
    }

    protected JSONObject checkBody(String body) {
        JSONObject object = JsonUtils.parseObject(body, JSONObject.class);
        if (object.containsKey("success") && !object.getBoolean("success")) {
            throw new AuthException(object.getString("msg"));
        }
        return object;
    }

    protected JSONObject doPostMengniuRequest(String data, HttpHeader header, String url) {
        String body = (new HttpUtils(this.config.getHttpConfig())).post(url, data, header).getBody();
        return checkBody(body);
    }

    protected JSONObject doGetMengniuRequest(HttpHeader header, String url) {
        String body = (new HttpUtils(this.config.getHttpConfig())).get(url, null, header, false).getBody();
        return checkBody(body);
    }

    private HttpHeader getHeader() {
        String appSecret = this.config.getClientSecret();
        String appid = this.config.getClientId();
        HttpHeader httpHeader = new HttpHeader();
        String base64 = "basic " + Base64.encode(appid + ":" + appSecret);
        httpHeader.add("token-client", base64);
        return httpHeader;
    }

    public Boolean logout(String token) {
        HttpHeader httpHeader = new HttpHeader();
        httpHeader.add("token-auth", token);
        doGetMengniuRequest(httpHeader, authMengniuSource.userLoginout());
        return true;
    }

    public JSONArray userRoles(String token) {
        HttpHeader httpHeader = new HttpHeader();
        httpHeader.add("token-auth", token);
        JSONObject jsonObject = doGetMengniuRequest(httpHeader, authMengniuSource.userRoles());
        return jsonObject.getJSONArray("data");
    }

    public JSONArray userRoutes(String token) {
        HttpHeader httpHeader = new HttpHeader();
        httpHeader.add("token-auth", token);
        JSONObject jsonObject = doGetMengniuRequest(httpHeader, authMengniuSource.userRoutes());
        return jsonObject.getJSONArray("data");
    }

    public JSONArray userPerms(String token) {
        HttpHeader httpHeader = new HttpHeader();
        httpHeader.add("token-auth", token);
        JSONObject jsonObject = doGetMengniuRequest(httpHeader, authMengniuSource.userPerms());
        return jsonObject.getJSONArray("data");
    }


    @Override
    protected AuthToken getAccessToken(AuthCallback authCallback) {
        //拼接header
        HttpHeader httpHeader = getHeader();
        //拼接body
        String code = authCallback.getCode();
        TokenRequestBody tokenRequestBody = new TokenRequestBody();
        tokenRequestBody.setCode(code);

        String data = JsonUtils.toJsonString(tokenRequestBody);
        JSONObject object = doPostMengniuRequest(data, httpHeader, this.source.accessToken());
        // user 验证异常
        JSONObject jsonObject = object.getJSONObject("data");

        JSONObject refreshToken = jsonObject.getJSONObject("refreshToken");
        /**
         * {
         *     "tokenType":"bearer",
         *     "token":"9216681af86125509d4d6e5aee6b794d",
         *     "expiration":"2023-12-05 04:49:22",
         *     "refreshToken":{
         *         "token":"70d3da45d594e0424d760e816bf56f76",
         *         "expiration":"2023-12-14 18:49:22",
         *         "expiresIn":847686
         *     },
         *     "additionalInformation":{
         *
         *     },
         *     "expiresIn":19686,
         *     "expired":false
         * }
         */
        String accessToken = jsonObject.getString("token");
        String tokenType = jsonObject.getString("tokenType");
        String realToken=tokenType+" "+accessToken;
        Integer expiresIn = jsonObject.getInteger("expiresIn");
        //存入redis
        RedisUtils.setCacheObject(CacheConstants.SOCIAL_AUTH_CODE_ACCESSTOKEN + authCallback.getState(), realToken, Duration.ofMinutes(expiresIn));
        return AuthToken.builder()
                .tokenType(jsonObject.getString("tokenType"))
                .accessToken(accessToken)
                .expireIn(jsonObject.getInteger("expiresIn"))
                .refreshToken(refreshToken.getString("token"))
                .refreshTokenExpireIn(refreshToken.getInteger("expiresIn"))
                .build();
    }


    @Override
    protected AuthMengniuUser getUserInfo(AuthToken authToken) {
        HttpHeader httpHeader = getHeader();
        httpHeader.add("token-auth", "bearer " + authToken.getAccessToken());
        JSONObject object = doGetMengniuRequest(httpHeader, this.source.userInfo());
        JSONObject data = object.getJSONObject("data");
        /**
         * {
         *     "code":200,
         *     "success":true,
         *     "data":{
         *         "userId":"21ef931d08c1cf2b453d142da93ac70c",
         *         "username":"俞登刚(集团数字科技部(外部))",
         *         "number":"E100052781",
         *         "mobile":"19156076698",
         *         "mail":"",
         *         "avatarUrl":"",
         *         "extendsInfo":{
         *
         *         }
         *     },
         *     "msg":"操作成功"
         * }
         */
        AuthMengniuUser authMengniuUser = new AuthMengniuUser();
        authMengniuUser.setUuid(data.getString("userId"));
        authMengniuUser.setUsername(data.getString("number"));
        authMengniuUser.setNickname(data.getString("username"));
        authMengniuUser.setAvatar(data.getString("avatarUrl"));
        authMengniuUser.setCompany("蒙牛");
        authMengniuUser.setEmail(data.getString("email"));
        authMengniuUser.setToken(authToken);
        authMengniuUser.setSource(this.source.toString());
        authMengniuUser.setRawUserInfo(data.getJSONObject("extendsInfo"));
        authMengniuUser.setMobile(data.getString("mobile"));
        JSONObject authMengniuUserExt = getAuthMengniuUserExt(authToken.getAccessToken());
        authMengniuUser.setAuthMengniuUserExt(authMengniuUserExt);
        return authMengniuUser;
    }

    //获取用户扩展信息
    public JSONObject getAuthMengniuUserExt(String token) {
        HttpHeader httpHeader = getHeader();
        httpHeader.add("token-auth", "bearer " + token);
        JSONObject object = doGetMengniuRequest(httpHeader, this.authMengniuSource.userInfoExt());
        return object.getJSONObject("data");

    }

    //组装授权地址 格式是：https://98kgw.mengniu.cn/auth/oauth2/v2/authorize?client_id=xxx&state=xxx
    @Override
    public String authorize(String state) {
        return UrlBuilder.fromBaseUrl(this.source.authorize())
                .queryParam("client_id", this.config.getClientId())
                .queryParam("state", this.getRealState(state)).build();
    }

}
